#include "patronus_public.h"

typedef struct
{
	void *frontend;
	void *backend;
} self_session_t;

int initialize();
int handle_frontend	(zloop_t *loop, void *socket, void *arg);
int handle_backend	(zloop_t *loop, void *socket, void *arg);

int
main(int args, char *argv[])
{
	initialize();
	TINYLOG_INFO("START");

    zctx_t *ctx = zctx_new ();
	self_session_t *self = (self_session_t *)zmalloc(sizeof(self_session_t));

    //  Frontend socket talks to clients over TCP
    void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
    zsocket_bind (frontend, "tcp://*:8743");

    //  Backend socket talks to workers over TCP 
    void *backend = zsocket_new (ctx, ZMQ_DEALER);
    zsocket_bind (backend, "tcp://*:8744");

	self->frontend = frontend;
	self->backend = backend;

	zloop_t * reactor = zloop_new();
	zloop_reader(reactor, self->frontend, handle_frontend, self);
	zloop_reader(reactor, self->backend, handle_backend, self);

	zloop_start(reactor);
	zloop_destroy(&reactor);

	zsocket_destroy(ctx, frontend);
	zsocket_destroy(ctx, backend);
    zctx_destroy (&ctx);
	free(self);

	assert(reactor == NULL);
	
	TINYLOG_INFO("EXIT");
	return EXIT_SUCCESS;
}



//	-----------------------------------------------------------------------
//	when get the message from yb device, do this func

int
handle_frontend(zloop_t *loop, void *socket, void *arg)
{
	self_session_t *self = (self_session_t *)arg;
	assert(self != NULL);
	zmsg_t *msg = zmsg_recv(self->frontend);

	//	TODO:TEST  how fast the handle speed is
	//~ start handle msg
	if (msg) {
		zmsg_dump(msg);	
		zframe_t *address = zmsg_first(msg);
		msg_head_t *msg_head = (msg_head_t*) zframe_data(zmsg_next(msg));
		
		if (MSG_TYPE_CONNECT == msg_head->type) {
			msg_connect_t *msg_connect = (msg_connect_t*) malloc(sizeof(msg_connect_t));
			msg_connect->IMEI	= *(long long *)zframe_data(zmsg_next(msg));
			msg_connect->email	= (char *)zframe_data(zmsg_next(msg));
			//fprintf(stderr, "%s\n", msg_connect->email);
			zmsg_destroy(&msg);

		} else {//if ( MSG_TYPE_CHAT_TEXT == msg_head->type) {
			fprintf(stderr, "devcie from : %d, to : %d\n", 
					msg_head->yb_device_id_from,
					msg_head->yb_device_id_to);

			//deliver the msg to the right yb device id 
			//disgard the address frame	
			zmsg_unwrap(msg);
			
			if (0 != msg_head->yb_device_id_to){
				char address_to[8] = {0};
				sprintf(address_to, "%X", msg_head->yb_device_id_to);
			
				//add the new address
				zmsg_pushstr(msg, address_to);
				zmsg_dump(msg);	

				zmsg_send(&msg, self->frontend);
			} else {
				//send to worker
				TINYLOG_INFO("send to worker");
				zmsg_send(&msg, self->backend);
			}
		}
	}
	//:~ end

	return 0;
}

//	-----------------------------------------------------------------------
//	when get the message from yb worker, do this func

int
handle_backend(zloop_t *loop, void *socket, void *arg)
{
	fprintf(stderr, "i'm in backend\n");
	return 0;
}


int
initialize()
{
	// init tinylog
	tinylog_layout_t * layout = tinylog_new_layout("ybrouter_full",
			tinylog_get_layout_type_by_name("full"), NULL);
	void * appender = tinylog_new_appender("ybrouter_stderr", "stream");
	tinylog_reg_layout_to_appender(appender, layout);
	tinylog_stream_appender_set_fp(appender, stderr);
	tinylog_reg_appender(appender);

	FILE * fp = fopen("./runtime-ybrouter.log", "a");
	if (NULL != fp) {
		layout = tinylog_new_layout("ybrouter_full",
				tinylog_get_layout_type_by_name("full"), NULL);
		void * appender = tinylog_new_appender("ybrouter_file", "stream");
		tinylog_reg_layout_to_appender(appender, layout);
		tinylog_stream_appender_set_fp(appender, fp);
		tinylog_reg_appender(appender);
	} else {
		TINYLOG_CRIT("can't open log file: %s", strerror(errno));
	}

	return 0;
}
